package controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;

import javax.swing.JDialog;

import org.apache.commons.beanutils.BeanUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import util.HibernateUtil;
import view.AddBookPage;
import bean.Book;
import bean.Catalog;

import com.mysql.jdbc.StringUtils;

import dto.BookDTO;
import dto.LogonDTO;

public class AddBookController {

	private AddBookPage addBook;
	private CommonBookController commonController;
	private BookDTO dto;
	private String userName;
	private String errorMessage;

	void addBook(LogonDTO logonDTO) {
		commonController = new CommonBookController();
		userName = logonDTO.getUserName();

		addBook = new AddBookPage(logonDTO);

		addBook.addAddBookButtonListener(new AddBookListener());
		addBook.addGetISBNInfoButtonListener(commonController.new GetISBNInfoListener(
				addBook));

		addBook.setModal(true);
		addBook.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		addBook.setVisible(true);
	}

	class AddBookListener implements ActionListener {

		public void actionPerformed(ActionEvent arg0) {
			dto = addBook.getBookDTO();

			if (validateBookEntry()) {
				addBookToDB();
				addBook.displayMessage("\"" + dto.getTitle()
						+ "\" has been added.");
				addBook.clearFields();
			} else {
				addBook.displayMessage(errorMessage);
			}
		}
	}

	private boolean validateBookEntry() {

		boolean isValid = true;

		if (StringUtils.isNullOrEmpty(dto.getTitle())) {
			errorMessage = "Title field should not be empty.";
			isValid = false;
		} else if (StringUtils.isNullOrEmpty(dto.getAuthor())) {
			errorMessage = "Author field should not be empty.";
			isValid = false;
		} else if (StringUtils.isNullOrEmpty(dto.getISBN())) {
			errorMessage = "ISBN field should not be empty.";
			isValid = false;
		} else if (StringUtils.isNullOrEmpty(dto.getDeweyDecimalNo())) {
			errorMessage = "Catalog field should not be empty.";
			isValid = false;
		}

		if (commonController.fetchCatalogByDDC(dto.getDeweyDecimalNo()) != null) {
			errorMessage = "Catalog Number(DDC) already exists.";
			isValid = false;
		}

		return isValid;
	}

	private void addBookToDB() {

		Book bookBean = new Book();
		Catalog catalogBean = new Catalog();

		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.openSession();
		Transaction transaction;

		try {

			// already exists in DB, so insert into Catalog only
			Book book = commonController.fetchBookByISBN(dto.getISBN());
			if (book != null) {
				catalogBean.setBook(book);
				catalogBean.setOnLoan("N");
				catalogBean.setDeweyDecimalNo(dto.getDeweyDecimalNo());
				catalogBean.setEditedBy(userName);
				catalogBean.setEditedDate(getCurrentTime());

				transaction = session.beginTransaction();
				session.save(catalogBean);
				transaction.commit();
			} else {
				// insert into Book and Catalog

				BeanUtils.copyProperties(bookBean, dto);
				bookBean.setEditedBy(userName);
				bookBean.setEditedDate(getCurrentTime());

				transaction = session.beginTransaction();
				session.save(bookBean);
				transaction.commit();

				catalogBean.setBook(bookBean);
				catalogBean.setOnLoan("N");
				catalogBean.setDeweyDecimalNo(dto.getDeweyDecimalNo());
				catalogBean.setEditedBy(userName);
				catalogBean.setEditedDate(getCurrentTime());

				transaction = session.beginTransaction();
				session.save(catalogBean);
				transaction.commit();
			}
		} catch (IllegalAccessException iae) {
			iae.printStackTrace();
		} catch (InvocationTargetException ite) {
			ite.printStackTrace();
		}
	}

	private Timestamp getCurrentTime() {
		java.util.Date date = new java.util.Date(System.currentTimeMillis());
		java.sql.Timestamp timestamp = new java.sql.Timestamp(date.getTime());

		return timestamp;
	}

}
